//------- Constants --------
float4x4 View;
float4x4 Projection;
float4x4 World;

float4 TintColor;
float4 AlphaColor;

//------- Texture Samplers --------

Texture SrcTexture;
Texture MskTexture;
sampler SrcSampler = sampler_state
{
	texture = <SrcTexture>;
	magfilter = LINEAR;
	minfilter = LINEAR;
	mipfilter = LINEAR;
	AddressU = wrap;
	AddressV = wrap;
};
sampler MskSampler = sampler_state
{
	texture = <MskTexture>;
	magfilter = LINEAR;
	minfilter = LINEAR;
	mipfilter = LINEAR;
	AddressU = wrap;
	AddressV = wrap;
};

//------- Vertex formats

struct PosTex {
	float4 position : POSITION;
	float2 texcoord : TEXCOORD0;
};
struct PosColTex {
	float4 position : POSITION;
	float4 color    : COLOR;
	float2 texcoord : TEXCOORD0;
};
struct PosColTex2 {
	float4 position : POSITION;
	float4 color    : COLOR;
	float2 texcoord	: TEXCOORD0;
	float2 mskcoord : TEXCOORD1;
};
struct ColTex2 {
	float4 color    : COLOR;
	float2 texcoord	: TEXCOORD0;
	float2 mskcoord : TEXCOORD1;
};
struct ColTex {
	float4 color    : COLOR;
	float2 texcoord : TEXCOORD0;
};
struct PosTex2 {
	float4 position : POSITION;
	float2 texcoord : TEXCOORD0;
	float2 mskcoord : TEXCOORD1;
};
struct Tex {
	float2 texcoord : TEXCOORD0;
};
struct Tex2 {
	float2 texcoord : TEXCOORD0;
	float2 mskcoord : TEXCOORD1;
};

//------- General purpose technique

uniform bool Tinting = false;
uniform bool MaskTex = false;
uniform bool BlendAlpha = false;

//------- State variables

extern uniform float time = 0;
extern uniform float4 diffuse = float4(1,1,1,1);
extern uniform float4 specular = float4(0,0,0,1);

//------- Common Functions

float4 transPosition(float4 pos) {
	float4 wp = mul(pos, World);
	float4 vp = mul(wp, View);
	return mul(vp, Projection);
}

ColTex transColor(ColTex input) {
	float4 output = tex2D(SrcSampler, input.texcoord);
	if(Tinting) {
		output = float4(
			output.r * input.color.r,
			output.g * input.color.g,
			output.b * input.color.b,
			output.a);
	}
	if(BlendAlpha) {
		if(distance(output, AlphaColor) < 0.01)
			output = float4(0,0,0,0);
	}
	if(MaskTex) {
		float4 msk = tex2D(MskSampler, input.texcoord);
		// assuming the masking texture is a grey scale
		output = float4(
			output.r * msk.r,
			output.g * msk.g,
			output.b * msk.b,
			output.a * msk.a);
	}
	
	output.r = output.r * (diffuse.r + specular.r * output.r);
	output.g = output.g * (diffuse.g + specular.g * output.g);
	output.b = output.b * (diffuse.b + specular.b * output.b);
	
	input.color = output;
	return input;
}

//------- General Purpose Functions

PosColTex genVertexShader(PosColTex input) {
	PosColTex output = input;
	output.position = transPosition(input.position);
	return output;
}

float4 genPixelShader(ColTex input) : COLOR {
	return transColor(input).color;
}

// Note: all other techniques are obsolete
technique GeneralTechnique
{
	pass
	{
		VertexShader = compile vs_2_0 genVertexShader();
		PixelShader = compile ps_2_0 genPixelShader();
	}
}

//------- Heat wave technique

uniform float HeatStrength;
uniform float HeatPhase;

PosColTex hwvVertexShader(PosColTex input) {
	float ampy = HeatStrength * sin((input.position.x + 2*input.position.y)/3.0 * time * (1.0/HeatPhase));
	float ampx = HeatStrength * cos((input.position.x + input.position.y)/3.0 * time * (1.0/HeatPhase));
	
	input.position.y = input.position.y + ampy;
	input.position.x = input.position.x + ampx;
	
	input.position = transPosition(input.position);
	return input;
}

technique HeatWaveTechnique
{
	pass
	{
		VertexShader = compile vs_2_0 hwvVertexShader();
		PixelShader = compile ps_2_0 genPixelShader();
	}
}

//-------- Rainstorm technique

uniform bool tdsIsThunder = false;	// true, if the color should be adjusted for a lightning
uniform float tdsTime = 0;			// what time is it, relative to the initial flash?
uniform float tdsAmp = 0;			// how strong is the thunder?
uniform float tdsDuration = 1.0;	// how long does a flash last?

Texture tdsTexture;
sampler tdsSampler = sampler_state
{
	texture = <tdsTexture>;
	mipfilter = LINEAR;
	AddressU = wrap;
	AddressV = wrap;
};

uniform float tdsSrcF = 0.7;
uniform float tdsTdrF = 0.3;

float4 tdsPixelShader(ColTex input) : COLOR {
	float4 output = transColor(input).color;
	
	if(tdsIsThunder) {
		float amp = tex2D(tdsSampler, float2(tdsTime/tdsDuration, tdsAmp));
		output.r = (tdsSrcF * output.r + tdsTdrF * output.r * amp);
		output.g = (tdsSrcF * output.g + tdsTdrF * output.g * amp);
		output.b = (tdsSrcF * output.b + tdsTdrF * output.b * amp);
	}
	return output;
}

technique RainStormTechnique
{
	pass
	{
		VertexShader = compile vs_2_0 genVertexShader();
		PixelShader = compile ps_2_0 tdsPixelShader();
	}
}

